package com.ruoyi.biz.report.letter.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.biz.letter.domain.*;
import com.ruoyi.biz.letter.mapper.*;
import com.ruoyi.biz.letter.util.SysDeptUtil;
import com.ruoyi.biz.report.letter.vo.*;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.mapper.SysDeptMapper;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Fei.Cong
 * @date 2024-07-30 14:37
 */
@Service
@RequiredArgsConstructor
public class ReportService {

    private final SysDeptMapper sysDeptMapper;
    private final BizCityLetterMapper bizCityLetterMapper;
    private final BizMayorHotlineMapper bizMayorHotlineMapper;
    private final BizLeaderMailboxMapper bizLeaderMailboxMapper;
    private final BizMessageBoardMapper bizMessageBoardMapper;
    private final BizProvinceLetterMapper bizProvinceLetterMapper;
    private final BizRecordLetterMapper bizRecordLetterMapper;
    private final CategoryService categoryService;

    @DataScope(deptAlias = "d")
    public List<ReportResp> getCityClaimReport(ReportReq reportReq) {
        SysDept sysDept = new SysDept();
        sysDept.setDeptId(reportReq.getDeptId());
        sysDept.setParentId(100L);
        sysDept.setParams(reportReq.getParams());
        List<SysDept> deptList = sysDeptMapper.selectDeptList(sysDept);
        List<Map<String, Object>> cityLetterList = summary(reportReq);
        BizCityLetter bizCityLetter = new BizCityLetter();
        bizCityLetter.setBillMonths(DateUtils.getMonthRange(reportReq.getBeginDate(), reportReq.getEndDate()));
        List<ReportChild> reportChildList = bizCityLetterMapper.selectReport(bizCityLetter);

        List<ReportResp> reportVOS = Lists.newArrayList();
        for (SysDept dept : deptList) {
            List<Long> childList = SysDeptUtil.getChildList(dept.getDeptId());
            ReportResp reportResp = new ReportResp();
            reportResp.setDeptName(dept.getDeptName());
            reportResp.setDeptId(dept.getDeptId());

            List<BigInteger> waitCount = Lists.newArrayList();
            List<BigInteger> finishedCount = Lists.newArrayList();
            List<BigInteger> dispatchCount = Lists.newArrayList();
            List<BigInteger> backCount = Lists.newArrayList();
            for (Long childDeptId : childList) {
                this.getSummaryChildCity(cityLetterList, waitCount, finishedCount, dispatchCount, backCount,childDeptId, reportResp);
            }
            reportResp.setChildren(reportChildList.stream().filter(v -> Objects.equals(v.getDeptId(), dept.getDeptId())).collect(Collectors.toList()));
            reportVOS.add(reportResp);
        }
        return reportVOS;
    }

    private void getSummaryChildCity(List<Map<String, Object>> cityLetterList, List<BigInteger> waitCount, List<BigInteger> finishedCount, List<BigInteger> dispatchCount,List<BigInteger> backCount, Long childDeptId, ReportResp reportResp) {
        for (Map<String, Object> cityLetterMap : cityLetterList) {
            if (Objects.equals(childDeptId, cityLetterMap.get("deptId"))) {
                switch (cityLetterMap.get("status").toString()) {
                    case "1":
                        waitCount.add(new BigInteger(cityLetterMap.get("cnt").toString()));
                        break;
                    case "2":
                        finishedCount.add(new BigInteger(cityLetterMap.get("cnt").toString()));
                        break;
                    case "3":
                        dispatchCount.add(new BigInteger(cityLetterMap.get("cnt").toString()));
                        break;
                    case "4":
                        backCount.add(new BigInteger(cityLetterMap.get("cnt").toString()));
                        break;
                }
            }
        }
        BigInteger waitSum = waitCount.stream().reduce(BigInteger.ZERO, BigInteger::add);
        BigInteger finishedSum = finishedCount.stream().reduce(BigInteger.ZERO, BigInteger::add);
        BigInteger dispatchSum = dispatchCount.stream().reduce(BigInteger.ZERO, BigInteger::add);
        BigInteger backSum = backCount.stream().reduce(BigInteger.ZERO, BigInteger::add);
        reportResp.setImp(waitSum.add(finishedSum).add(dispatchSum).add(backSum));
        reportResp.setWait(waitSum);
        reportResp.setFinished(finishedSum);
        reportResp.setDispatch(dispatchSum);
        reportResp.setBack(backSum);
    }

    private List<Map<String, Object>> summary(ReportReq reportReq) {
        List<String> monthRange = DateUtils.getMonthRange(reportReq.getBeginDate(), reportReq.getEndDate());
        QueryWrapper<BizCityLetter> wrapper = new QueryWrapper<>();
        wrapper.select("count(*) as cnt,dept_id as deptId,status")
                .groupBy("dept_id", "status");
        wrapper.in("bill_month", monthRange);
        return bizCityLetterMapper.selectMaps(wrapper);
    }

    public List<HomePageResp> getHomePageSummary() {
        String year = String.valueOf(DateUtil.year(new Date()));
        String month = DateUtil.format(new Date(), "yyyy-MM");
        List<HomePageResp> homePageRespList = Lists.newArrayList();
        buildHotlineCnt(month, year, homePageRespList);
        buildMailboxCnt(month, year, homePageRespList);
        buildMessageBoardCnt(month, year, homePageRespList);
        buildProvinceCnt(month, year, homePageRespList);
        buildCityCnt(month, year, homePageRespList);
        buildLetterCnt(month, year, homePageRespList);
        buildTelgramCnt(month, year, homePageRespList);
        buildVisitCnt(month, year, homePageRespList);
        return homePageRespList;
    }

    private void buildHotlineCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizMayorHotlineMapper.selectCount(new LambdaQueryWrapper<BizMayorHotline>().last(" where date_format(letter_time,'%Y-%m') = '" + month + "'"));
        Long yearCnt = bizMayorHotlineMapper.selectCount(new LambdaQueryWrapper<BizMayorHotline>().last(" where date_format(letter_time,'%Y')= '" + year + "'"));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(1L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("mayor:hotline:list");
        homePageRespList.add(homePageResp);
    }

    private void buildMailboxCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizLeaderMailboxMapper.selectCount(new LambdaQueryWrapper<BizLeaderMailbox>().last(" where date_format(letter_time,'%Y-%m') = '" + month + "'"));
        Long yearCnt = bizLeaderMailboxMapper.selectCount(new LambdaQueryWrapper<BizLeaderMailbox>().last(" where date_format(letter_time,'%Y')= '" + year + "'"));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(2L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("leader:mailbox:list");
        homePageRespList.add(homePageResp);
    }

    private void buildMessageBoardCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizMessageBoardMapper.selectCount(new LambdaQueryWrapper<BizMessageBoard>().last(" where date_format(submit_time,'%Y-%m') = '" + month + "'"));
        Long yearCnt = bizMessageBoardMapper.selectCount(new LambdaQueryWrapper<BizMessageBoard>().last(" where date_format(submit_time,'%Y')= '" + year + "'"));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(3L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("message:board:list");
        homePageRespList.add(homePageResp);
    }

    private void buildProvinceCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizProvinceLetterMapper.selectCount(new LambdaQueryWrapper<BizProvinceLetter>().last(" where date_format(letter_time,'%Y-%m') = '" + month + "'"));
        Long yearCnt = bizProvinceLetterMapper.selectCount(new LambdaQueryWrapper<BizProvinceLetter>().last(" where date_format(letter_time,'%Y')= '" + year + "'"));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(7L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("province:letter:list");
        homePageRespList.add(homePageResp);
    }

    private void buildCityCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizCityLetterMapper.selectCount(new LambdaQueryWrapper<BizCityLetter>().last(" where date_format(letter_time,'%Y-%m') = '" + month + "'"));
        Long yearCnt = bizCityLetterMapper.selectCount(new LambdaQueryWrapper<BizCityLetter>().last(" where date_format(letter_time,'%Y')= '" + year + "'"));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(8L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("city:letter:list");
        homePageRespList.add(homePageResp);
    }

    private void buildLetterCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizRecordLetterMapper.selectCount(new LambdaQueryWrapper<BizRecordLetter>().last(" where date_format(letter_time,'%Y-%m') = '" + month + "' and source=1 "));
        Long yearCnt = bizRecordLetterMapper.selectCount(new LambdaQueryWrapper<BizRecordLetter>().last(" where date_format(letter_time,'%Y')= '" + year + "' and source=1 "));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(4L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("record:letter:list");
        homePageRespList.add(homePageResp);
    }

    private void buildTelgramCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizRecordLetterMapper.selectCount(new LambdaQueryWrapper<BizRecordLetter>().last(" where date_format(letter_time,'%Y-%m') = '" + month + "' and source=2 "));
        Long yearCnt = bizRecordLetterMapper.selectCount(new LambdaQueryWrapper<BizRecordLetter>().last(" where date_format(letter_time,'%Y')= '" + year + "' and source=2 "));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(5L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("record:telgram:list");
        homePageRespList.add(homePageResp);
    }

    private void buildVisitCnt(String month, String year, List<HomePageResp> homePageRespList) {
        Long monthCnt = bizRecordLetterMapper.selectCount(new LambdaQueryWrapper<BizRecordLetter>().last(" where date_format(letter_time,'%Y-%m') = '" + month + "' and source=3 "));
        Long yearCnt = bizRecordLetterMapper.selectCount(new LambdaQueryWrapper<BizRecordLetter>().last(" where date_format(letter_time,'%Y')= '" + year + "' and source=3 "));
        HomePageResp homePageResp = new HomePageResp();
        homePageResp.setId(6L);
        homePageResp.setYearCnt(yearCnt);
        homePageResp.setMonthCnt(monthCnt);
        homePageResp.setPermission("record:visit:list");
        homePageRespList.add(homePageResp);
    }

    public HomePageLineResp getLineChartSummary() {
        List<ReportYearCategoryResp> reportDatas = bizRecordLetterMapper.selectReportGroupMonthAndSource();
        Map<String, List<ReportYearCategoryResp>> sourceMap = reportDatas.stream().collect(Collectors.groupingBy(ReportYearCategoryResp::getSource));
        HomePageLineResp homePageLineResp = new HomePageLineResp();
        List<String> x = Lists.newArrayList();
        List<Integer> lxList = Lists.newArrayList();
        List<Integer> ldList = Lists.newArrayList();
        List<Integer> lfList = Lists.newArrayList();
        for (int i = 11; i >= 0; i--) {
            x.add(DateUtil.format(DateUtil.offsetMonth(new Date(), -i), "yyyy-MM"));
        }
        for (int j = 1; j <= 3; j++) {
            for (int i = 11; i >= 0; i--) {
                String month = DateUtil.format(DateUtil.offsetMonth(new Date(), -i), "yyyy-MM");
                switch (j) {
                    case 1:
                        buildLineChartData(sourceMap, lxList, month, "1");
                        break;
                    case 2:
                        buildLineChartData(sourceMap, ldList, month, "2");
                        break;
                    case 3:
                        buildLineChartData(sourceMap, lfList, month, "3");
                        break;
                }
            }
        }
        homePageLineResp.setX(x);
        homePageLineResp.setLxData(lxList);
        homePageLineResp.setLdData(ldList);
        homePageLineResp.setLfData(lfList);
        return homePageLineResp;
    }

    private void buildLineChartData(Map<String, List<ReportYearCategoryResp>> sourceMap, List<Integer> lxList, String month, String f) {
        List<ReportYearCategoryResp> letterLists = sourceMap.get(f);
        Map<String, List<ReportYearCategoryResp>> billMonthMap = letterLists.stream().collect(Collectors.groupingBy(ReportYearCategoryResp::getBillMonth));
        if (billMonthMap.containsKey(month)) {
            lxList.add(Integer.parseInt(billMonthMap.get(month).get(0).getCnt().toString()));
        } else {
            lxList.add(0);
        }
    }

    public List<HomePageBarResp> getGoverBarChartSummary() {
        String month = DateUtil.format(new Date(), "yyyy-MM");
        List<TreeSelect> categoryList = categoryService.getCategoryList();
        List<CategoryCount> hotlineCategorys = bizMayorHotlineMapper.selectReportGroupCategory(month);
        List<CategoryCount> mailboxCategorys = bizLeaderMailboxMapper.selectReportGroupCategory(month);
        List<CategoryCount> messageCountList = bizMessageBoardMapper.selectReportGroupCategory(month);
        List<HomePageBarResp> homePageBarRespList = Lists.newArrayList();
        for (TreeSelect treeSelect : categoryList) {
            HomePageBarResp homePageBarResp = new HomePageBarResp();
            homePageBarResp.setCategoryName(treeSelect.getLabel());
            homePageBarResp.setHotline(buildBarCnt(hotlineCategorys, treeSelect.getValue()));
            homePageBarResp.setMailbox(buildBarCnt(mailboxCategorys, treeSelect.getValue()));
            homePageBarResp.setMessage(buildBarCnt(messageCountList, treeSelect.getValue()));
            homePageBarRespList.add(homePageBarResp);
        }
        return homePageBarRespList;
    }

    public List<HomePageBarResp> getVisitBarChartSummary() {
        String month = DateUtil.format(new Date(), "yyyy-MM");
        List<TreeSelect> categoryList = categoryService.getCategoryList();
        List<CategoryCount> provinceCategorys = bizProvinceLetterMapper.selectReportGroupCategory(month);
        List<CategoryCount> cityCategorys = bizCityLetterMapper.selectReportGroupCategory(month);
        List<CategoryCount> letterCategorys = bizRecordLetterMapper.selectReportGroupCategory(month, 1);
        List<CategoryCount> telegramCategorys = bizRecordLetterMapper.selectReportGroupCategory(month, 2);
        List<CategoryCount> visitCategorys = bizRecordLetterMapper.selectReportGroupCategory(month, 3);
        List<HomePageBarResp> homePageBarRespList = Lists.newArrayList();
        for (TreeSelect treeSelect : categoryList) {
            HomePageBarResp homePageBarResp = new HomePageBarResp();
            homePageBarResp.setCategoryName(treeSelect.getLabel());
            homePageBarResp.setLetter(buildBarCnt(letterCategorys, treeSelect.getValue()));
            homePageBarResp.setTelegram(buildBarCnt(telegramCategorys, treeSelect.getValue()));
            homePageBarResp.setVisit(buildBarCnt(visitCategorys, treeSelect.getValue()));
            homePageBarResp.setProvince(buildBarCnt(provinceCategorys, treeSelect.getValue()));
            homePageBarResp.setCity(buildBarCnt(cityCategorys, treeSelect.getValue()));
            homePageBarRespList.add(homePageBarResp);
        }
        return homePageBarRespList;
    }

    private Integer buildBarCnt(List<CategoryCount> categoryCountList, String firstCategoryId) {
        if (CollectionUtil.isNotEmpty(categoryCountList)) {
            Map<String, Integer> categoryMap = categoryCountList.stream().collect(Collectors.toMap(k -> k.getFirstCategoryId(), v -> v.getCnt()));
            if (categoryMap.containsKey(firstCategoryId)) {
                return categoryMap.get(firstCategoryId);
            }
        }
        return 0;
    }

}
